package com.test.spring.sliding;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author ll
 * 滑动窗口
 * @Date 2017/7/11 14:07
 */
public class SlotBasedCounter<T> {

    private int slotSize;

    private ConcurrentHashMap<T, AtomicInteger[]> objToCounts = new ConcurrentHashMap<>();

    public SlotBasedCounter(int slotSize) {
        this.slotSize = slotSize < 1 ? 1 : slotSize;
    }

    public void incrementCount(T t, int slot) {
        AtomicInteger[] counts = objToCounts.get(t);
        if (counts == null) {
            counts = new AtomicInteger[this.slotSize];
            for (int i = 0; i < this.slotSize; i++) {
                counts[i] = new AtomicInteger(0);
            }
            objToCounts.put(t, counts);
        }
        counts[slot].incrementAndGet();
    }

    public Map<T, Long> getCounts() {
        Map<T, Long> result = new HashMap<>();
        for (T t : objToCounts.keySet()) {
            result.put(t, getTotalCount(t));
        }
        return result;
    }

    public Long getTotalCount(T t) {
        AtomicInteger[] curr = objToCounts.get(t);
        long total = 0;
        if (curr != null) {
            for (AtomicInteger atomicInteger : curr) {
                total += atomicInteger.get();
            }
        }
        return total;
    }

    public void wipeSlot(int slot){
        for (T t : objToCounts.keySet()) {
            resetSlotCountToZero(t, slot);
        }
    }

    private void resetSlotCountToZero(T t, int slot) {
        AtomicInteger[] counts = objToCounts.get(t);
        counts[slot].set(0);
    }

    private boolean shouldBeRemovedFromCounter(T t) {
        return getTotalCount(t) == 0;
    }

    public void wipeZeros() {
        Set<T> objToBeRemoved = new HashSet<>();
        for (T t : objToCounts.keySet()) {
            if (shouldBeRemovedFromCounter(t)) {
                objToBeRemoved.add(t);
            }
        }
    }
}
